package org.KeyCrafter.server.session;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.channel.Channel;
import io.netty.handler.codec.redis.RedisMessage;
import io.netty.util.AttributeKey;
import org.KeyCrafter.cmd.Command;
import org.KeyCrafter.server.DefaultKVDB;
import org.KeyCrafter.server.KVDB;

import java.util.ArrayList;
import java.util.List;

/**
 * 用户缓存类
 * 用于暂时缓存服务端处理完的客户端命令
 * 待客户端文件描述的可写事件发生时，向真正客户端发送命令回复
 */
public final class ClientSession {
    public static final int KeyCrafter_FORCE_AOF = (1<<14);
    public static final String KEY_NAME = "client_session";
    public static final AttributeKey<ClientSession> ATTRIBUTE_KEY = AttributeKey.valueOf(KEY_NAME);
    private static final int KeyCrafter_MAX_QUERYBUF_LEN = 1024*1024*1024;
    // 连接通道
    private Channel channel;

    // 客户端的名字
    private String name;

    // 客户端标志
    private int flags;

    // 当前正在使用的数据库
    private KVDB db;

    // 参数数量
    private int argc;

    // 参数对象数组
    private List<String> argv;

    // 客户端当前执行的命令
    private Command cmd;

    // 查询缓冲区
    private CompositeByteBuf queryBuf;

    // 回复信息
    private RedisMessage replyMessage;

    // 回复缓冲区（简短常用消息直接付给message，
    // 长消息或bulk消息先存到buffer再转成message）
    private ByteBuf replyBuffer;

    public Channel channel() {
        return channel;
    }

    public String name() {
        return name;
    }

    public int argc() {
        return argc;
    }

    public List<String> argv() {
        return this.argv;
    }

    public String argv(int i) {
        if (i >= argc || i < 0) {
            return null;
        } else {
            return argv.get(i);
        }
    }

    public Command cmd() {
        return this.cmd;
    }
    // 当前正在使用的 db
    public KVDB db() {
        return this.db;
    }

    public RedisMessage getReplyMessage() {
        return this.replyMessage;
    }

    public ByteBuf getReplyBuffer() {
        return this.replyBuffer;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    public void setName(String name) {
        this.name = name;
    }

    // 设置回复信息
    public void setReplyMessage(RedisMessage reply) {
        this.replyMessage = reply;
    }

    public void setCurDB(KVDB db) {
        this.db = db;
    }


    public void setArgc(int argc) {
        this.argc = argc;
    }

    public void setArgv(int index, String value) {
        argv.set(index,value);
    }

    public void addArgv(String value) {
        argv.add(value);
    }

    public void setCmd(Command cmd) {
        this.cmd = cmd;
    }

    // 是否有信息
    public boolean hasReplyMessage() {
        return this.replyMessage != null;
    }

    // 是否有缓冲
    public boolean hasReplyBuffer() {
        return this.replyBuffer != null && replyBuffer.isReadable();
    }

    public CompositeByteBuf getQueryBuf() {
        return queryBuf;
    }

    public void setQueryBuf(CompositeByteBuf queryBuf) {
        this.queryBuf = queryBuf;
    }

    public int getFlags() {
        return flags;
    }

    public void setFlags(int flags) {
        this.flags = flags;
    }

    public void addFlag(int flag) {
        this.flags |= flag;
    }


    // 清空回复
    public void clearReply() {
        this.replyMessage = null;
        this.replyBuffer.clear();
    }

    public ClientSession(Channel channel) {
        // 默认数据库
        KVDB.selectDb(this,0);
        // 初始化参数
        this.channel = channel;
        this.name = null;
        this.argc = 0;
        this.argv = new ArrayList<>();
        this.cmd = null;
        // 申请查询缓冲区
        this.queryBuf = channel.alloc().compositeBuffer();
        // 申请回复缓冲区
        this.replyBuffer = channel.alloc().buffer();
    }

    public ClientSession() {
        // 默认数据库
        KVDB.selectDb(this,0);
        // 初始化参数
        this.argc = 0;
        this.argv = new ArrayList<>();
    }

    // 客户端重置
    public void resetArgAndCmd() {
        this.argc = 0;
        this.argv.clear();
        this.cmd = null;
    }
}
